package com.atguigu.gulimall.search.ThreadTest;

import java.util.concurrent.*;

public class CompletableFuture {
    //supply有返回值，run没有返回值
    //线程池
    //1、原生 1)Executors
    //       2)new ThreadPoolExecutor()
    //       六大参数
    //       1、corePoolSize 核心线程数量 , 核心线程一直存在 ，除非设置allowCoreThreadTimeOut
    //       2、maximumPoolSize 最大线程数量; 当队列满了，就开新线程，最多不能不能线程池中允许的最大线程数量，用来控制资源
    //       3、keepAliveTime 释放空闲线程的最大时间，只释放非核心线程
    //       4、BlockingQueue<Runnable> 存放任务的队列 阻塞队列，多的任务放到队列里，空闲的线程去队列中拿
    //             new linkedBlockingDeque<>() 默认的最大数量是Integer的最大值，
    //             不设置容量就会沾满内存，因此一般要设置容量，这个要根据系统任务的大小来设置
    //       5、threadFactory 创建线程的工厂默认就行
    //       6、handler 处理队列满了该怎么办，按照指定的拒绝策略执行
    //          拒绝策略 ： DiscardOldestPolicy 丢弃不抛异常，丢弃最老的任务
    //                    CallerRunsPolicy 启动run方法
    //                    AbortPolicy 直接丢弃，抛异常
    //                    DiscardPolicy 丢弃 不抛异常，丢弃最新的任务
    // 2、种类
    //        1、newCachedThreadPool() 缓存线程池，没有核心的线程；
    //        2、newFixedThreadPool() 固定线程池，核心等于最大，都不可回收
    //        3、newScheduledThreadPool 定时任务的线程池，提交任务指定多长时间后执行；
    //        4、newSingleThreadPool 单线程的线程池，后台从队列中获取任务，挨个执行
    // 3、为什么使用线程池
    //    1、控制资源，防止无限的创建和销毁现象导致系统资源耗尽而崩溃
    //    2、节省了频繁创建的销毁线程的开销
    //    3、提高了任务的响应速度，任务一进来就被已经创建好的线程处理
    // 4、异步编排，编排线程的执行顺序CompletableFuture,某个线程执行完了后面的线程再执行
    //
    //    1、创建方式 runAsync和supplyAsync，runAsync没有返回值，supplyAsync有返回值
    //              Executor executor 是使用自己自定义的线程池执行任务
    //       1、CompletableFuture.runAsync(()->{})
    //       2、CompletableFuture.runAsync(()->{},Executor executor);
    //       3、CompletableFuture.supplyAsync(()->{});
    //       4、CompletableFuture.supplyAsync(()->{},Executor executor)
    //    2、开始编排
    //      1、方法完成后的感知：
    //       1、whenComplete((result,exceptipn))； 前面的任务完成之后该怎么办，可以得到信息，不能修改返回数据
    //       2、exceptionally(throwable->{ }); 出异常该怎么办，可以修改返回结果
    //      2、方法完成后的处理
    //       1、handle((res,thr))->{
    //          if(res!=null){
    //             return res*2;}
    //          if(thr!=null){
    //             return 0;}
    //          })
    //       3、编排方法
    //        1、后面的任务在前面的任务完成的基础上执行
    //          1、thenRunAsync(Runnable action,Executor executor)
    //          2、thenRun；
    //          RunAsync是开新线程执行,thenRun是使用旧线程
    //          ，这里不需要前面的执行结果，没有返回值
    //
    //          1、thenAcceptAsync(Consumer<? super T> action,Executor executor)
    //          2、thenAccept();
    //          thenAccept可以接收前面的结果，没有返回值
    //
    //          1、CompletableFuture thenApply(Function<? super T>, fn)
    //             thenApply会拿到之前的返 回结果，
    //             处理了之后再返回，既有前面的结果，又有返回值
    //
    //          1、对于一个异步的处理
    //              1、thenRun/Async()
    //              2、thenAccept/Async()
    //              3、theApply/Async()
    //
    //          2、对于两个异步的处理
    //
    //           1）、一个任务完成就执行，不需要两个都完成再执行
    //               1、runAfterEither（other，action, executor） //无返回值，无接收值
    //               2、acceptEither（other，action, executor）//有接收值，无返回值
    //               3、applyToEither（other，fn(T,U), action, executor）// 有接收值，有返回值

    //            2）、两个都完成再进行
    //               1、runAfterBoth(CompletionStage<?> other, Runable action, Execute execute)
    //               2、thenAcceptBoth(CompletionStage<?> other,BioConsumer<? super T,? super U>，Runable action, Execute execute)
    //               3、thenCombine()   //有接收值，有返回值，两个任务都完成再执行
    //
    //
    //
    //            3、多任务组合
    //               1、allof   所有的任务完成再执行
    //               2、anyof   其中又一个任务完成就执行
    //
    //
    //
    //
    //
    //
    //  private static final ExecutorService SECKILL_ORDER_EXECUTOR = Executors.newSingleThreadExecutor();

    private static final ExecutorService executors = Executors.newFixedThreadPool(10);

    public static void main(String[] args) throws ExecutionException, InterruptedException {

        java.util.concurrent.CompletableFuture<Integer> future = java.util.concurrent.CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程" + Thread.currentThread().getId());
            int i = 10 / 2;
            System.out.println("运行结果" + i);
            System.out.println(i);
            return i;
        }, executors);

        Integer a = future.get();
        System.out.println("main end "+a);
    }
}
